package sliceformUtils;

import pluginUtils.Plane;
import pluginUtils.Pos3D;


/** Une droite definie dans un espace a trois dimensions : un point et un vecteur directeur **/
public class DroiteSpace3D {
	protected Pos3D point;  // vu comme un point
	protected Pos3D direction;  // vu comme un vecteur directeur
	
	public DroiteSpace3D(Pos3D point, Pos3D direction) {
		super();
		this.point = point;
		this.direction = direction;
	}
	
	public DroiteSpace3D rotate(CoupleDAngles rot){
		//System.out.println("Point avant "+point); 
		//System.out.println("Point apres "+point.rotate(rot)); 
		return new DroiteSpace3D(point.rotate(rot), direction.rotate(rot)); 
	}
	
	public DroiteSpace3D rotateInverse(CoupleDAngles rot){
		return new DroiteSpace3D(point.rotateInverse(rot), direction.rotateInverse(rot)); 
	}
	
	// TODO : pas tres efficace
	public boolean belongs(Pos3D A){
		
		double cx=(A.getX()-point.getX())/direction.getX(); 
		double cy=(A.getY()-point.getY())/direction.getY(); 
		double cz=(A.getZ()-point.getZ())/direction.getZ(); 
		boolean xy=Math.abs(1-(cx/cy))<1e-6; 
		boolean xz=Math.abs(1-(cx/cz))<1e-6; 
		boolean yz=Math.abs(1-(cy/cz))<1e-6;
		return xy&&xz&&yz; 	
	}
	
	public DroiteSpace3D translate(Pos3D p){
		Pos3D newPoint=Pos3D.add(this.point,p); 
		return new DroiteSpace3D(newPoint, this.direction); 
	}
	
	public String toString(){
		String s="Droite de vecteur directeur "+this.direction+"\n et passant par "+this.point; 
		return s; 
	}

	public Pos3D getPoint() {
		return point;
	}

	public Pos3D getDirection() {
		return direction;
	}

	/** Droite definie comme l'intersection de deux droites **/	
	public static Pos3D intersection(DroiteSpace3D biss1_2,
			DroiteSpace3D biss1_3) {
			Pos3D A1=biss1_2.getPoint(); //A1
			Pos3D B1=biss1_3.getPoint(); // B1
			Pos3D v1=biss1_2.getDirection(); // A2-A1
			Pos3D v2=biss1_3.getDirection();  // B2-B1
			Pos3D dirAux=Pos3D.sub(A1,B1); 
			Pos3D c1=Pos3D.produitvectoriel(v2, dirAux); 
			Pos3D c2=Pos3D.produitvectoriel(v1, v2);
			double nA=c1.produitScalaire(c2); 
			Pos3D c3=Pos3D.produitvectoriel(v1, dirAux); 
			double nB=c3.produitScalaire(c2); 
			double d=c2.produitScalaire(c2); // norme au carre
			Pos3D resuA=Pos3D.add(A1,Pos3D.mul(v1, nA/d)); 
			Pos3D resuB=Pos3D.add(B1,Pos3D.mul(v2, nB/d)); 
			//System.out.println(" intersection (1) "+resuA); 
			//System.out.println("intersection (2) " +resuB); 
			return resuA; 
			
	
	}
	
	/** Droite definie comme l'intersection de deux plans **/
	public static DroiteSpace3D inter(Plane p1,Plane p2){
		if((p1.getA()==0)&&(p2.getA()!=0)){
			Plane temp=p1; p1=p2; p2=temp;
		}
		if((p1.getA()==0)&&(p2.getA()==0)){ // droite de direction (1,0,0) (ou bien plan paralleles, pas de solution)
			if((p1.getB()==0)&&(p2.getB()==0)) return null; // plans paralleles
			if((p1.getB()==0)&&(p2.getB()!=0)){
				Plane temp=p1; p1=p2; p2=temp;
			}
			// Chercher un point (x,y,z)
			double bdm=p2.getB()*p1.getD()-p1.getB()*p2.getD(); 
			double cbm=p2.getC()*p1.getB()-p1.getC()*p2.getB(); 
			double zconstante=bdm/cbm;
			double yconstante=-p1.getC()/p1.getB()*zconstante-(p1.getD()/p1.getB()); 
			Pos3D lepoint=new Pos3D(0,yconstante,zconstante); 
			Pos3D ladirection=new Pos3D(1,0,0);
			return new DroiteSpace3D(lepoint,ladirection); 
		}
		
		double ab=p1.getA()*p2.getB()-p1.getB()*p2.getA(); 
		if(ab==0) // vecteur directeur dans le plan xOy (composante nulle selon z)
		{
			double bdm=p2.getB()*p1.getD()-p1.getB()*p2.getD(); 
			double cbm=p2.getC()*p1.getB()-p1.getC()*p2.getB(); 
			double zconstante=bdm/cbm;
			double yconstante=-1/p1.getB()*(p1.getC()*zconstante-p1.getD());
			Pos3D lepoint=new Pos3D(0,yconstante,zconstante);
			Pos3D ladirection=new Pos3D(1,-p1.getA()/p1.getB(),0); 
			return new DroiteSpace3D(lepoint,ladirection); 
		}
		double adm=p2.getA()*p1.getD()-p1.getA()*p2.getD(); 
		double acm=p2.getA()*p1.getC()-p1.getA()*p2.getC();
		double yconstante=adm/ab; 
		double zconstante=0; 
		double xconstante=-p1.getB()/p1.getA()*(adm/ab)-p1.getD()/p1.getA(); 
		double zcoef=1; 
		double ycoef=acm/ab; 
		double xcoef=-p1.getB()/p1.getA()*(acm/ab)-p1.getC()/p1.getA(); 
		Pos3D lepoint=new Pos3D(xconstante,yconstante,zconstante);
		Pos3D ladirection=new Pos3D(xcoef,ycoef,zcoef); 
		return new DroiteSpace3D(lepoint,ladirection); 
	}
	

}
